package cn.edu.neu.vmmigeval.cloud.policy.impl;


import cn.edu.neu.vmmigeval.cloud.config.Migration;
import cn.edu.neu.vmmigeval.cloud.entity.Host;
import cn.edu.neu.vmmigeval.cloud.entity.Vm;
import cn.edu.neu.vmmigeval.cloud.policy.MigratedHostPolicy;
import cn.edu.neu.vmmigeval.cloud.policy.VmPlacementPolicy;

import java.util.ArrayList;
import java.util.List;

public class VmPlacementPolicyBestFromRandomHeuristic extends VmPlacementPolicy {

	public VmPlacementPolicyBestFromRandomHeuristic(List<Host> hostList,
			MigratedHostPolicy migratedHostPolicy) {
		super(hostList, migratedHostPolicy);
	}
	
	public VmPlacementPolicyBestFromRandomHeuristic(){
		
	}
	
	public VmPlacementPolicyBestFromRandomHeuristic(
			MigratedHostPolicy migratedHostPolicy) {
		super( migratedHostPolicy);
	}

	public List<Migration> getNewVmPlacement(List<Vm> vmsToMigrate, List<Host> hosts){
		
		
		List<Migration> migs = new ArrayList<Migration>();
		for (Vm vm : vmsToMigrate) {
			Host targetHost = findHostForVm(vm,getExcludedHosts(hosts));
			if (targetHost != null) {
				
				Host srcHost = vm.getHost();
				vm.setInMigration(true);
				List<Vm> vms = new ArrayList<Vm>();
				vms.add(vm);
				Migration migration = new Migration();
				migration.setSrcHost(srcHost);
				migration.setDestHost(targetHost);
				migration.setVms(vms);
				migration.setClocks((int)((vm.getCurrentRam()/(srcHost.getTotalBw()-srcHost.getCurrentBw())))+1);
				//System.out.println("clocks is :"+migration.getClocks());
				migration.setEnd(false);
				
				srcHost.setMigration(true);
				targetHost.setMigration(true);
				targetHost.setActive(0);
				migs.add(migration);
			}
		}
		return migs;
		
		/*for(int i=1;i<1000;i++){   //��1000�η��䷽��������õķ��䷽��
			List<Vm> vms = shuffle(vmsToMigrate);
			int size = vmsToMigrate.size();
			for(int j=0;j<size;j++){
				Vm vm = vms.remove(0);
				for(Host host : hosts){
					if(host.isSuitableForVm(vm)){
						if(!isHostOverUtilizedAfterAllocation(host, vm)){
							Migration migrate = new Migration();
							vm.setInMigration(true);
							migrate.setSrcHost(vm.getHost());
							migrate.setDestHost(host);
							List<Vm>  vmstemp = new LinkedList<Vm>();
							vms.add(vm);
							migrate.setVms(vmstemp);
							bestMigration.add(migrate);
						}
					}
				}
			}
			if(countPower(newMigration) < countPower(bestMigration)){
				bestMigration = newMigration;
			}			
		}*/
		
		//return bestMigration;
	}
	public Host findHostForVm(Vm vm,List<Host> hosts){
		
		if(hosts!=null&&hosts.size()!=0){
			
			int size = hosts.size();
			int num = 0;
			while(num<size){
				int rand = (int)(Math.random()*hosts.size());
				Host sHost =hosts.get(rand);
				if(sHost.isSuitableForVm(vm)){
					return sHost;
				}
				num++;
			}
		}
		return null;
		
	}
	
	
//	/**
//	 * Checks if is host over utilized after allocation.
//	 *
//	 * @param host the host
//	 * @param vm the vm
//	 * @return true, if is host over utilized after allocation
//	 */
	/*protected boolean isHostOverUtilizedAfterAllocation(Host host, Vm vm) {
		boolean isHostOverUtilizedAfterAllocation = true;
		if (host.vmCreate(vm)) {
			isHostOverUtilizedAfterAllocation = this.getMigratedHostPolicy().isHostOverUtilized(host);
			host.vmDestroy(vm);
		}
		return isHostOverUtilizedAfterAllocation;
	}*/
	
	private List<Vm> shuffle(List<Vm> vmList){
		List<Vm> vms = new ArrayList<Vm>();
		int size = vmList.size();
		for(int i= 0;i<size;i++){
			int index = (int)Math.random()*vmList.size();
			vms.add(vmList.remove(index));
		}
		return vms;
	}
	
	private double countPower(List<Migration> migrations){
		return 1.0;
	}
}
